home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / dns / checker / new_named / ns_req.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-24  |  32.5 KB  |  1,392 lines

  1. /*
  2.  * Copyright (c) 1986, 1988, 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted provided
  6.  * that: (1) source distributions retain this entire copyright notice and
  7.  * comment, and (2) distributions including binaries display the following
  8.  * acknowledgement:  ``This product includes software developed by the
  9.  * University of California, Berkeley and its contributors'' in the
  10.  * documentation or other materials provided with the distribution and in
  11.  * all advertising materials mentioning features or use of this software.
  12.  * Neither the name of the University nor the names of its contributors may
  13.  * be used to endorse or promote products derived from this software without
  14.  * specific prior written permission.
  15.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  16.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  17.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18.  */
  19.  
  20. #ifndef lint
  21. static char sccsid[] = "@(#)ns_req.c    4.44 (Berkeley) 6/27/90";
  22. #endif /* not lint */
  23.  
  24. #include <stdio.h>
  25. #include <sys/param.h>
  26. #include <sys/uio.h>
  27. #include <sys/time.h>
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <syslog.h>
  31. #include <sys/file.h>
  32. #include <arpa/nameser.h>
  33. #include "ns.h"
  34. #include "db.h"
  35.  
  36. #define NADDRECS    20
  37.  
  38. extern    int    debug;
  39. extern    FILE    *ddt;
  40.  
  41. struct addinfo {
  42.     char    *a_dname;        /* domain name */
  43.     u_short    a_class;        /* class for address */
  44. };
  45.  
  46. struct    addinfo addinfo[NADDRECS];    /* additional info records */
  47. int    addcount;            /* number of names in addinfo */
  48. int    xfr_disabled = 0;        /* set to disable zone xfrs */
  49. int    needs_prime_cache = 0;        /* set if we need a priming */
  50.  
  51. u_char    *dnptrs[20];        /* ptrs to dnames in message for dn_comp */
  52.  
  53. #ifdef CHECKER
  54. extern u_long  checker();
  55. #endif
  56.  
  57. extern time_t retrytime();
  58. extern struct qinfo *sysquery();
  59. extern char *localdomain;    /* XXX */
  60. extern int errno;
  61. /*
  62.  * Process request using database; assemble and send response.
  63.  */
  64. ns_req(msg, msglen, buflen, qsp, from, dfd)
  65.     u_char *msg;
  66.     int msglen, buflen;
  67.     struct qstream *qsp;
  68.     struct sockaddr_in *from;
  69.     int dfd;
  70. {
  71.     register HEADER *hp;
  72.     register u_char *cp;
  73.     struct namebuf *np;
  74.     register struct databuf *dp;
  75.     struct hashbuf *htp;
  76.     struct netinfo *lp;
  77.     char *fname, *answers;
  78.     u_char *eom, *omsg;
  79.     char dnbuf[MAXDNAME], *dname;
  80.     u_char **dpp;
  81.     int n, class, type, count, foundname, founddata, omsglen, cname = 0;
  82.     u_short id;
  83.     struct databuf *nsp[NSMAX];
  84.     struct qinfo *qp;
  85.     extern struct qinfo *qhead;
  86.     extern struct netinfo *local();
  87.     extern int nsid;
  88.  
  89. #ifdef DEBUG
  90.     if (debug > 3) {
  91.         fprintf(ddt,"ns_req()\n");
  92.         fp_query(msg, ddt);
  93.     }
  94. #endif
  95.  
  96.     hp = (HEADER *) msg;
  97.     if (hp->qr) {
  98.         ns_resp(msg, msglen);
  99.  
  100.         /* Now is a safe time for housekeeping */
  101.         if (needs_prime_cache)
  102.             prime_cache();
  103.         return;
  104.     }
  105.  
  106.     hp->rcode = NOERROR;
  107.     cp = msg + sizeof(HEADER);
  108.     eom = msg + msglen;
  109.     dpp = dnptrs;
  110.     *dpp++ = msg;
  111.     addcount = 0;
  112.  
  113. #ifdef CHECKER
  114.         checker( 0, msg, msglen, from, qsp );
  115. #endif
  116.  
  117.     switch (hp->opcode) {
  118.     case QUERY:
  119. #ifdef STATS
  120.         stats[S_QUERIES].cnt++;
  121. #endif
  122.         if (ntohs(hp->qdcount) != 1 ||
  123.             hp->ancount || hp->nscount || hp->arcount) {
  124. #ifdef DEBUG
  125.             if (debug)
  126.                 fprintf(ddt,"FORMERR Query header counts wrong\n");
  127. #endif
  128.             hp->qdcount = 0;
  129.             hp->ancount = 0;
  130.             hp->nscount = 0;
  131.             hp->arcount = 0;
  132.             hp->rcode = FORMERR;
  133.             goto finish;
  134.         }
  135.         /*
  136.          * Get domain name, class, and type.
  137.          */
  138.         if ((*cp & INDIR_MASK) == 0)
  139.             *dpp++ = cp;    /* remember name for compression */
  140.         *dpp = NULL;
  141.         if ((n = dn_expand(msg, eom, cp, dnbuf,
  142.             sizeof(dnbuf))) < 0) {
  143. #ifdef DEBUG
  144.             if (debug)
  145.                 fprintf(ddt,"FORMERR Query expand name failed\n");
  146. #endif
  147.             hp->rcode = FORMERR;
  148.             goto finish;
  149.         }
  150.         cp += n;
  151.         GETSHORT(type, cp);
  152.         GETSHORT(class, cp);
  153.         if (cp > eom) {
  154. #ifdef DEBUG
  155.             if (debug)
  156.                 fprintf(ddt,"FORMERR Query message length short\n");
  157. #endif
  158.             hp->rcode = FORMERR;
  159.             goto finish;
  160.         }
  161. #ifdef DEBUG
  162.         if (cp < eom)
  163.             if (debug > 5)
  164.                 fprintf(ddt,"message length > received message\n");
  165. #endif
  166.  
  167. #ifdef STATS
  168.         if ((type > T_ANY) || (type < 0))
  169.             typestats[0]++;    /* Bad type */
  170.         else
  171.             typestats[type]++;
  172. #endif
  173.         /*
  174.          * Process query.
  175.          */
  176.         if (type == T_AXFR) {
  177.             /* refuse request if not a TCP connection */
  178.             if (qsp == QSTREAM_NULL || xfr_disabled) {
  179. #ifdef DEBUG
  180.                 if (debug)
  181.                     fprintf(ddt,"T_AXFR via UDP refused\n");
  182. #endif
  183.                 hp->rcode = REFUSED;
  184.                 goto finish;
  185.             }
  186.             dnptrs[0] = NULL;    /* don't compress names */
  187.             hp->rd = 0;        /* recursion not possible */
  188.         }
  189.         buflen -= msglen;
  190.         count = 0;
  191.         foundname = 0;
  192.         founddata = 0;
  193.         dname = dnbuf;
  194. try_again:
  195. #ifdef DEBUG
  196.         if (debug)
  197.             fprintf(ddt,"req: nlookup(%s) id %d type=%d\n",
  198.                 dname, hp->id, type);
  199. #endif
  200.         htp = hashtab;        /* lookup relative to root */
  201.         if ((np = nlookup(dname, &htp, &fname, 0)) == NULL)
  202.             fname = "";
  203. #ifdef DEBUG
  204.         if (debug)
  205.             fprintf(ddt,"req: %s '%s' as '%s' (cname=%d)\n",
  206.                 np == NULL ? "missed" : "found",
  207.                 dname, fname, cname);
  208. #endif
  209.         /* START XXX */
  210.         /*
  211.          * if nlookup failed to find address then
  212.          *  see if there are any '.''s in the name
  213.          * if not then add local domain name to the
  214.          * name and try again.
  215.          */
  216.         if (np == NULL && localdomain && index(dname, '.') == NULL) {
  217.             (void) strcat(dname,".");
  218.             (void) strcat(dname, localdomain);
  219. #ifdef DEBUG
  220.             if (debug)
  221.                 fprintf(ddt,"req: nlookup(%s) type=%d\n",
  222.                     dname, type);
  223. #endif
  224.             htp = hashtab;
  225.             np = nlookup(dname, &htp, &fname, 0);
  226.             }
  227.         /* END XXX */
  228.         if (np == NULL || fname != dname)
  229.             goto fetchns;
  230.  
  231.         foundname++;
  232.         answers = (char *)cp;
  233.         count = cp - msg;
  234.         n = finddata(np, class, type, hp, &dname, &buflen, &count);
  235.         if (n == 0)
  236.             goto fetchns;        /* NO data available */
  237.         cp += n;
  238.         buflen -= n;
  239.         msglen += n;
  240.         hp->ancount += count;
  241.         if (fname != dname && type != T_CNAME && type != T_ANY) {
  242.             if (cname++ >= MAXCNAMES) {
  243. #ifdef DEBUG
  244.                 if (debug >= 3)
  245.                     fprintf(ddt,
  246.                     "resp: leaving, MAXCNAMES exceeded\n");
  247. #endif
  248.                 hp->rcode = SERVFAIL;
  249.                 goto finish;
  250.             }
  251.             goto try_again;
  252.         }
  253.         founddata = 1;
  254. #ifdef DEBUG
  255.         if (debug >= 3) {
  256.             fprintf(ddt,"req: foundname = %d count = %d ", foundname, count);
  257.             fprintf(ddt,"founddata = %d cname = %d\n",founddata, cname);
  258.         }
  259. #endif
  260.         if ((lp = local(from)) != NULL) 
  261.             sort_response(answers, count, lp, cp);
  262.         if (type == T_AXFR) {
  263.             if (founddata) {
  264.                 hp->ancount = htons(hp->ancount);
  265.                 startxfr(qsp, np, msg, cp - msg);
  266.                 return;
  267.             }
  268.             hp->rcode = REFUSED;    /* No go if unauthoritative */
  269.             goto finish;
  270.         }
  271. #ifdef notdef
  272.         /*
  273.          * If we found an authoritative answer,
  274.          * we're done.
  275.          */
  276.         if (hp->aa)
  277.             goto finish;
  278. #endif
  279.  
  280. fetchns:
  281.         /*
  282.           * Look for name servers to refer to and fill in the authority
  283.           * section or record the address for forwarding the query
  284.           * (recursion desired).
  285.           */
  286.         nsp[0] = NULL;
  287.         count = 0;
  288.         switch (findns(&np, class, nsp, &count)) {
  289.         case NXDOMAIN:
  290.             if (!foundname)
  291.                 hp->rcode = NXDOMAIN;
  292. #ifdef DEBUG
  293.             if (debug >= 3)
  294.                 fprintf(ddt,"req: leaving (%s, rcode %d)\n",
  295.                     dname, hp->rcode);
  296. #endif
  297.             if (class != C_ANY) {
  298.                 hp->aa = 1;
  299.                 /* XXX
  300.                  * should return SOA if founddata == 0,
  301.                  * but old named's are confused by an SOA
  302.                  * in the auth. section if there's no error.
  303.                  */
  304.                 if (foundname == 0 && np) {
  305.                     n = doaddauth(hp, cp, buflen, np, nsp[0]);
  306.                     cp += n;
  307.                     buflen -= n;
  308.                 }
  309.             }
  310.             goto finish;
  311.  
  312.         case SERVFAIL:
  313.             if (!founddata) {
  314.                 hp->rcode = SERVFAIL;
  315.                 goto finish;
  316.             }
  317.         }
  318.  
  319.         /*
  320.          *  If we successfully found the answer in the cache
  321.          *  or this is not a recursive query, then add the
  322.          *  nameserver references here and return.
  323.          */
  324.         if (founddata || (!hp->rd)) {
  325.             n = add_data(np, nsp, cp, buflen);
  326.             if (n < 0) {
  327.                 hp->tc = 1;
  328.                 n = (-n);
  329.             }
  330.             cp += n;
  331.             buflen -= n;
  332.             hp->nscount = htons((u_short)count);
  333.             goto finish;
  334.         }
  335.  
  336.         /*
  337.          *  At this point, we don't have the answer, but we do
  338.          *  have some NS's to try.  If the user would like us
  339.          *  to recurse, create the initial query.  If a cname
  340.          *  is involved, we need to build a new query and save
  341.          *  the old one in cmsg/cmsglen.
  342.          */
  343.         if (cname) {
  344.             omsg = (u_char *)malloc((unsigned)msglen);
  345.             if (omsg == (u_char *)NULL) {
  346. #ifdef DEBUG
  347.                 if (debug)
  348.                         fprintf(ddt,"ns_req: malloc fail\n");
  349. #endif
  350.                 syslog(LOG_ERR, "ns_req: Out Of Memory");
  351.                 hp->rcode = SERVFAIL;
  352.                 break;
  353.             }
  354.             id = hp->id;
  355.             hp->ancount = htons(hp->ancount);
  356.             bcopy(msg, omsg, omsglen = msglen);
  357.             msglen = res_mkquery(QUERY, dname, class, type,
  358.                 (char *)NULL, 0, NULL, msg, msglen+buflen);
  359.         }
  360. #ifdef LAME_DELEGATION
  361.         n = ns_forw(nsp, msg, msglen, from, qsp, dfd, &qp, np);
  362. #else /* LAME DELEGATION */
  363.         n = ns_forw(nsp, msg, msglen, from, qsp, dfd, &qp);
  364. #endif /* LAME DELEGATION */
  365.         if (n != FW_OK && cname)
  366.             free(omsg);
  367.         switch (n) {
  368.         case FW_OK:
  369.             if (cname) {
  370.                 qp->q_cname = cname;
  371.                 qp->q_cmsg = (char *)omsg;
  372.                 qp->q_cmsglen = omsglen;
  373.                 qp->q_id = id;
  374.             }
  375.             break;
  376.         case FW_DUP:
  377.             break;        /* Duplicate request dropped */
  378.         case FW_NOSERVER:
  379.             if(np)
  380.                 np = np->n_parent;
  381.             goto fetchns;    /* Try again. */
  382.         case FW_SERVFAIL:
  383.             hp->rcode = SERVFAIL;
  384.             goto finish;
  385.         }
  386.         /* Now is a safe time for housekeeping */
  387.         if (needs_prime_cache)
  388.             prime_cache();
  389.         return;
  390.  
  391.     case IQUERY: {
  392.         register struct invbuf *ip;
  393.         register int i;
  394.         int dlen, alen;
  395.         char anbuf[PACKETSZ], *data;
  396.  
  397. #ifdef STATS
  398.         stats[S_IQUERIES].cnt++;
  399. #endif
  400.         hp->ancount = htons(hp->ancount);
  401.         if (hp->ancount != 1 ||
  402.             hp->qdcount || hp->nscount || hp->arcount) {
  403. #ifdef DEBUG
  404.             if (debug)
  405.                 fprintf(ddt,"FORMERR IQuery header counts wrong\n");
  406. #endif
  407.             hp->qdcount = 0;
  408.             hp->ancount = 0;
  409.             hp->nscount = 0;
  410.             hp->arcount = 0;
  411.             hp->rcode = FORMERR;
  412.             goto finish;
  413.         }
  414.         /*
  415.          * Skip domain name, get class, and type.
  416.          */
  417.         if ((n = dn_skipname(cp, eom)) < 0) {
  418. #ifdef DEBUG
  419.             if (debug)
  420.                 fprintf(ddt,"FORMERR IQuery packet name problem\n");
  421. #endif
  422.             hp->rcode = FORMERR;
  423.             goto finish;
  424.         }
  425.         cp += n;
  426.         GETSHORT(type, cp);
  427.         GETSHORT(class, cp);
  428.         cp += sizeof(u_long);
  429.         GETSHORT(dlen, cp);
  430.         cp += dlen;
  431.         if (cp != eom) {
  432. #ifdef DEBUG
  433.             if (debug)
  434.                 fprintf(ddt,"FORMERR IQuery message length off\n");
  435. #endif
  436.             hp->rcode = FORMERR;
  437.             goto finish;
  438.         }
  439.         /* not all inverse queries are handled. */
  440.         switch (type) {
  441.         case T_A:
  442.         case T_UID:
  443.         case T_GID:
  444.             break;
  445.  
  446.         default:
  447.             hp->rcode = REFUSED;
  448.             goto finish;
  449.         }
  450. #ifdef DEBUG
  451.         if (debug)
  452.             fprintf(ddt,"req: IQuery class %d type %d\n",
  453.                 class, type);
  454. #endif
  455.         fname = (char *)msg + sizeof(HEADER);
  456.         bcopy(fname, anbuf, alen = (char *)cp - fname);
  457.         data = anbuf + alen - dlen;
  458.         cp = (u_char *)fname;
  459.         buflen -= sizeof(HEADER);
  460.         count = 0;
  461.         for (ip = invtab[dhash(data, dlen)]; ip != NULL;
  462.             ip = ip->i_next) {
  463.             for (i = 0; i < INVBLKSZ; i++) {
  464.             if ((np = ip->i_dname[i]) == NULL)
  465.                 break;
  466. #ifdef DEBUG
  467.             if (debug >= 5)
  468.                 fprintf(ddt,"dname = %d\n", np->n_dname);
  469. #endif
  470.             for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  471.                 if (!match(dp, class, type))
  472.                     continue;
  473.                 if (dp->d_size != dlen ||
  474.                     bcmp(dp->d_data, data, dlen))
  475.                     continue;
  476.                 getname(np, dnbuf, sizeof(dnbuf));
  477. #ifdef DEBUG
  478.                 if (debug > 2)
  479.                     fprintf(ddt,"req: IQuery found %s\n",
  480.                         dnbuf);
  481. #endif
  482.                 buflen -= QFIXEDSZ;
  483.                 if ((n =
  484.                    dn_comp(dnbuf, cp, buflen, (char **)NULL,
  485.                       (char **)NULL)) < 0)
  486.                 {
  487.                     hp->tc = 1;
  488.                     goto finish;
  489.                 }
  490.                 cp += n;
  491.                 PUTSHORT((u_short)dp->d_type, cp);
  492.                 PUTSHORT((u_short)dp->d_class, cp);
  493.                 buflen -= n;
  494.                 count++;
  495.             }
  496.             }
  497.         }
  498. #ifdef DEBUG
  499.         if (debug)
  500.             fprintf(ddt,"req: IQuery %d records\n", count);
  501. #endif
  502.         hp->qdcount = htons((u_short)count);
  503.         if (alen > buflen) {
  504.             hp->tc = 1;
  505.             break;
  506.         }
  507.         bcopy(anbuf, cp, alen);
  508.         cp += alen;
  509.         break;
  510.         }
  511.  
  512. #ifdef ALLOW_UPDATES
  513. /*
  514.  * In a sense the following constant should be defined in <arpa/nameser.h>,
  515.  * since it is returned here in place of a response code if the update was
  516.  * forwarded, and the response codes are defined in nameser.h.  On the other
  517.  * hand, though, this constant is only seen in this file.  The assumption
  518.  * here is that none of the other return codes equals this one (a good
  519.  * assumption, since they only occupy 4 bits over-the-wire)
  520.  */
  521. #define FORWARDED 1000
  522.         /* Call InitDynUpdate for all dynamic update requests */
  523.         case UPDATEM:
  524.         case UPDATEMA:
  525.         case UPDATED:
  526.         case UPDATEDA:
  527.         case UPDATEA:
  528.                 n = InitDynUpdate(hp, nsp, msg, msglen, cp, from, qsp, dfd);
  529.                 if (n == FORWARDED)
  530.                         return; /* Return directly because InitDynUpdate
  531.                                  * forwarded the query to the primary, so we
  532.                                  * will send response later
  533.                                  */
  534.                 else
  535.                         break;  /* Either sucessful primary update or failure;
  536.                                  * return response code to client
  537.                                  */
  538. #endif ALLOW_UPDATES
  539.  
  540.     case ZONEREF:
  541. #ifdef DEBUG
  542.         if (debug)
  543.             fprintf(ddt,"Refresh Zone\n");
  544. #endif
  545.  
  546.     default:
  547. #ifdef DEBUG
  548.         if (debug >= 2)
  549.             fprintf(ddt,"Opcode %d not implemented\n", hp->opcode);
  550. #endif
  551.         hp->qdcount = 0;
  552.         hp->ancount = 0;
  553.         hp->nscount = 0;
  554.         hp->arcount = 0;
  555.         hp->rcode = NOTIMP;
  556.     }
  557. finish:
  558. #ifdef STATS
  559.     switch(hp->rcode) {
  560.     case NOERROR:
  561.         stats[S_RESPOK].cnt++;
  562.         break;
  563.     case FORMERR:
  564.         stats[S_RESPFORMERR].cnt++;
  565.         break;
  566.     default:
  567.         stats[S_RESPFAIL].cnt++;
  568.         break;
  569.     }
  570. #endif
  571.     hp->qr = 1;        /* set Response flag */
  572.     hp->ra = 1;        /* Recursion is Available */
  573.     hp->ancount = htons(hp->ancount);
  574.     if (addcount) {
  575.         n = doaddinfo(hp, cp, buflen);
  576.         cp += n;
  577.         buflen -= n;
  578.     }
  579.  
  580. #ifdef DEBUG
  581.     if (debug) {
  582.         fprintf(ddt,"req: answer -> %s %d (%d) id=%d %s\n",
  583.             inet_ntoa(from->sin_addr), 
  584.         qsp == QSTREAM_NULL ? dfd : qsp->s_rfd, 
  585.         ntohs(from->sin_port),
  586.         ntohs(hp->id), local(from) == NULL ? "Remote" : "Local");
  587.     }
  588.     if (debug >= 10)
  589.         fp_query(msg, ddt);
  590. #ifdef CHECKER
  591.         if( checker( 1, msg, cp-msg, from, qsp ) == 1 ) {
  592.             if( qsp != QSTREAM_NULL ) sq_done(qsp); }
  593.         else {
  594. #endif
  595.         
  596. #endif DEBUG
  597.     if (qsp == QSTREAM_NULL) {
  598.         if (sendto(dfd, msg, cp-msg, 0, (struct sockaddr *)from,
  599.             sizeof(*from))< 0){
  600. #ifdef DEBUG
  601.             if (debug)
  602.                 fprintf(ddt,"error returning msg errno=%d\n",errno);
  603. #endif DEBUG
  604.         }
  605. #ifdef STATS
  606.         stats[S_OUTPKTS].cnt++;
  607. #endif
  608.     } else {
  609.         (void) writemsg(qsp->s_rfd, msg, cp - msg);
  610.         sq_done(qsp);
  611.     }
  612. #ifdef CHECKER
  613.         }
  614. #endif
  615.     if (needs_prime_cache)
  616.         prime_cache();    /* Now is a safe time */
  617. }
  618.  
  619. fwritemsg(rfp, msg, msglen)
  620.     FILE *rfp;
  621.     char *msg;
  622.     int msglen;
  623. {
  624.     u_short len = htons((u_short)msglen);
  625.  
  626.     if (fwrite((char *)&len, sizeof(len), 1, rfp) != 1 ||
  627.         fwrite(msg, msglen, 1, rfp) != 1) {
  628. #ifdef DEBUG
  629.         if (debug)
  630.             fprintf(ddt,"fwrite failed %d\n", errno);
  631. #endif
  632.     }
  633.     return;
  634. }
  635.  
  636. writemsg(rfd, msg, msglen)
  637.     int rfd;
  638.     char *msg;
  639.     int msglen;
  640. {
  641.     struct iovec iov[2];
  642.     u_short len = htons((u_short)msglen);
  643.  
  644.     iov[0].iov_base = (caddr_t)&len;
  645.     iov[0].iov_len = sizeof(len);
  646.     iov[1].iov_base = msg;
  647.     iov[1].iov_len = msglen;
  648.     if (writev(rfd, iov, 2) != sizeof(len) + msglen) {
  649. #ifdef DEBUG
  650.         if (debug)
  651.             fprintf(ddt,"write failed %d\n", errno);
  652. #endif
  653.         return (-1);
  654.     }
  655.     return (0);
  656. }
  657.  
  658. /*
  659.  *  Test a datum for validity and return non-zero if it is out of date.
  660.  */
  661. stale(dp)
  662. register struct databuf *dp;
  663. {
  664.     register struct zoneinfo *zp = &zones[dp->d_zone];
  665.  
  666.     switch (zp->z_type) {
  667.  
  668.     case Z_PRIMARY:
  669.         return (0);
  670.  
  671.     case Z_SECONDARY:
  672.         /*
  673.          * Check to see whether a secondary zone
  674.          * has expired; if so clear authority flag
  675.          * for zone and return true.  If lastupdate
  676.          * is in the future, assume zone is up-to-date.
  677.          */
  678.         if ((long)(tt.tv_sec - zp->z_lastupdate) > (long)zp->z_expire) {
  679. #ifdef DEBUG
  680.             if (debug)
  681.                 fprintf(ddt,
  682.                     "stale: secondary zone %s expired\n",
  683.                     zp->z_origin);
  684. #endif
  685.             syslog(LOG_ERR, "secondary zone \"%s\" expired\n",
  686.                 zp->z_origin);
  687.             zp->z_auth = 0;
  688.             return (1);
  689.         }
  690.         return (0);
  691.  
  692.     case Z_CACHE:
  693. #ifdef DEBUG
  694.         if (debug >= 3)
  695.             fprintf(ddt,"stale: ttl %d %d (x%x)\n",
  696.                 dp->d_ttl, dp->d_ttl - tt.tv_sec, dp->d_flags);
  697. #endif
  698.         if (dp->d_flags & DB_F_HINT)
  699.             return(0);
  700.         return(dp->d_ttl < tt.tv_sec);
  701.  
  702.     }
  703.     /* NOTREACHED */
  704. }
  705.  
  706. /*
  707.  * Copy databuf into a resource record for replies.
  708.  * Return size of RR if OK, -1 if buffer is full.
  709.  */
  710. make_rr(name, dp, buf, buflen, doadd)
  711.     char *name;
  712.     register struct databuf *dp;
  713.     char *buf;
  714.     int buflen, doadd;
  715. {
  716.     register char *cp;
  717.     char *cp1, *sp;
  718.     struct zoneinfo *zp;
  719.     register long n;
  720.     register long ttl;
  721.     u_char **edp = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
  722.  
  723. #ifdef DEBUG
  724.     if (debug >= 5)
  725.         fprintf(ddt,"make_rr(%s, %x, %x, %d, %d) %d zone %d ttl %d\n",
  726.             name, dp, buf,
  727.             buflen, doadd, dp->d_size, dp->d_zone, dp->d_ttl);
  728. #endif
  729.  
  730.     zp = &zones[dp->d_zone];
  731.     /* check for outdated RR before updating dnptrs by dn_comp() (???) */
  732.     if (zp->z_type == Z_CACHE) {
  733.         ttl = dp->d_ttl - (u_long) tt.tv_sec;
  734.         if ((dp->d_flags & DB_F_HINT) || (ttl < 0)) {
  735. #ifdef DEBUG
  736. /*XXX*/if (debug >= 3) fprintf(ddt,"make_rr: %d=>0, x%x\n", ttl, dp->d_flags);
  737. #endif
  738.             ttl = 0;
  739.         }
  740.     } else {
  741.         if (dp->d_ttl)
  742.             ttl = dp->d_ttl;
  743.         else
  744.             ttl = zp->z_minimum;        /* really default */
  745. #ifdef notdef /* don't decrease ttl based on time since verification */
  746.         if (zp->z_type == Z_SECONDARY) {
  747.             /*
  748.              * Set ttl to value received from primary,
  749.              * less time since we verified it (but never
  750.              * less than a small positive value).
  751.              */
  752.             ttl -= tt.tv_sec - zp->z_lastupdate;
  753.             if (ttl <= 0)
  754.                 ttl = 120;
  755.         }
  756. #endif
  757.     }
  758.  
  759.     buflen -= RRFIXEDSZ;
  760.     if ((n = dn_comp(name, buf, buflen, (char **)dnptrs, (char **)edp)) < 0)
  761.         return (-1);
  762.     cp = buf + n;
  763.     buflen -= n;
  764.     PUTSHORT((u_short)dp->d_type, cp);
  765.     PUTSHORT((u_short)dp->d_class, cp);
  766.     PUTLONG(ttl, cp);
  767.     sp = cp;
  768.     cp += sizeof(u_short);
  769.     switch (dp->d_type) {
  770.     case T_CNAME:
  771.     case T_MG:
  772.     case T_MR:
  773.     case T_PTR:
  774.         if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs,
  775.            (char **)edp)) < 0)
  776.             return (-1);
  777.         PUTSHORT((u_short)n, sp);
  778.         cp += n;
  779.         break;
  780.  
  781.     case T_MB:
  782.     case T_NS:
  783.         /* Store domain name in answer */
  784.         if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs,
  785.            (char **)edp)) < 0)
  786.             return (-1);
  787.         PUTSHORT((u_short)n, sp);
  788.         cp += n;
  789.         if (doadd)
  790.             addname(dp->d_data, dp->d_class);
  791.         break;
  792.  
  793.     case T_SOA:
  794.     case T_MINFO:
  795.         cp1 = dp->d_data;
  796.         if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
  797.             (char **)edp)) < 0)
  798.             return (-1);
  799.         cp += n;
  800.         buflen -= dp->d_type == T_MINFO ? n : n + 5 * sizeof(u_long);
  801.         cp1 += strlen(cp1) + 1;
  802.         if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
  803.             (char **)edp)) < 0)
  804.             return (-1);
  805.         cp += n;
  806.         if (dp->d_type == T_SOA) {
  807.             cp1 += strlen(cp1) + 1;
  808.             bcopy(cp1, cp,
  809.                (int)(n = dp->d_size - (cp1 - dp->d_data)));
  810.             cp += n;
  811.         }
  812.         n = (u_short)(cp - sp) - sizeof(u_short);
  813.         PUTSHORT((u_short)n, sp);
  814.         break;
  815.  
  816.     case T_MX:
  817.         /* cp1 == our data/ cp == data of RR */
  818.         cp1 = dp->d_data;
  819.  
  820.          /* copy preference */
  821.          bcopy(cp1,cp,sizeof(u_short));
  822.          cp += sizeof(u_short);
  823.          cp1 += sizeof(u_short);
  824.          buflen -= sizeof(u_short);
  825.  
  826.           if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
  827.             (char **)edp)) < 0)
  828.               return(-1);
  829.           cp += n;
  830.  
  831.           /* save data length */
  832.           n = (u_short)(cp - sp) - sizeof(u_short);
  833.           PUTSHORT((u_short)n, sp);
  834.         if (doadd)
  835.             addname(cp1, dp->d_class);
  836.         break;
  837.  
  838.     default:
  839.         if (dp->d_size > buflen)
  840.             return (-1);
  841.         bcopy(dp->d_data, cp, dp->d_size);
  842.         PUTSHORT((u_short)dp->d_size, sp);
  843.         cp += dp->d_size;
  844.     }
  845.     return (cp - buf);
  846. }
  847.  
  848. addname(name, class)
  849. register char    *name;
  850. short    class;
  851. {
  852.     register struct addinfo *ap;
  853.     register int n;
  854.  
  855.     for (ap = addinfo, n = addcount; --n >= 0; ap++)
  856.         if (strcasecmp(ap->a_dname, name) == 0)
  857.             return;
  858.     /* add domain name to additional section */
  859.     if (addcount < NADDRECS) {
  860.         addcount++;
  861.         ap->a_dname = name;
  862.         ap->a_class = class;
  863.     }
  864. }
  865.  
  866. /*
  867.  * Lookup addresses for names in addinfo and put into the message's
  868.  * additional section.
  869.  */
  870. doaddinfo(hp, msg, msglen)
  871.     HEADER *hp;
  872.     char *msg;
  873.     int msglen;
  874. {
  875.     register struct namebuf *np;
  876.     register struct databuf *dp;
  877.     register struct addinfo *ap;
  878.     register char *cp;
  879.     struct hashbuf *htp;
  880.     char *fname;
  881.     int n, count, foundstale;
  882.  
  883. #ifdef DEBUG
  884.     if (debug >= 3)
  885.         fprintf(ddt,"doaddinfo() addcount = %d\n", addcount);
  886. #endif
  887.  
  888.     count = 0;
  889.     cp = msg;
  890.     for (ap = addinfo; --addcount >= 0; ap++) {
  891. #ifdef DEBUG
  892.         if (debug >= 3)
  893.             fprintf(ddt,"do additional '%s'\n", ap->a_dname);
  894. #endif
  895.         htp = hashtab;    /* because "nlookup" stomps on arg. */
  896.         np = nlookup(ap->a_dname, &htp, &fname, 0);
  897.         if (np == NULL || fname != ap->a_dname)
  898.             continue;
  899. #ifdef DEBUG
  900.         if (debug >= 3)
  901.             fprintf(ddt,"found it\n");
  902. #endif
  903.         foundstale = 0;
  904.         /* look for the data */
  905.         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  906.             if (!match(dp, (int)ap->a_class, T_A))
  907.                 continue;
  908.             if (stale(dp)) {
  909.                 foundstale++;
  910. #ifdef DEBUG
  911.                 if (debug)
  912.                     fprintf(ddt,"doaddinfo: stale entry '%s'%s\n",
  913.                         np->n_dname,
  914.                         (dp->d_flags&DB_F_HINT) ? " hint":"" );
  915. #endif
  916.                 continue;
  917.             }
  918.             /*
  919.              *  Should be smart and eliminate duplicate
  920.              *  data here.    XXX
  921.              */
  922.             if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0)) < 0)
  923.                 break;
  924. #ifdef DEBUG
  925.             if (debug >= 5)
  926.                 fprintf(ddt,"addinfo: adding address data n = %d\n",
  927.                    n);
  928. #endif
  929.             cp += n;
  930.             msglen -= n;
  931.             count++;
  932.         }
  933.         if (foundstale) {
  934.             /* Cache invalidate the address RR's */
  935.             delete_all(np, (int)ap->a_class, T_A);
  936.             (void) sysquery(ap->a_dname, (int)ap->a_class, T_A);
  937.         }
  938.     }
  939.     hp->arcount = htons((u_short)count);
  940.     return (cp - msg);
  941. }
  942.  
  943. doaddauth(hp, cp, buflen, np, dp)
  944.     register HEADER *hp;
  945.     char *cp;
  946.     int buflen;
  947.     struct namebuf *np;
  948.     struct databuf *dp;
  949. {
  950.     char dnbuf[MAXDNAME];
  951.     int n;
  952.  
  953.     getname(np, dnbuf, sizeof(dnbuf));
  954.     if (stale(dp) || (n = make_rr(dnbuf, dp, cp, buflen, 1)) <= 0) {
  955. #ifdef DEBUG
  956.         if (debug)
  957.             fprintf(ddt,"doaddauth: can't add '%s' (%d)\n",
  958.                 dnbuf, buflen);
  959. #endif
  960.         return(0);
  961.     } else {
  962.         hp->nscount = htons(1);
  963.         return(n);
  964.     }
  965. }
  966.  
  967.  
  968. /*
  969.  * Get the domain name of 'np' and put in 'buf'.  Bounds checking is done.
  970.  */
  971. getname(np, buf, buflen)
  972.     struct namebuf *np;
  973.     char *buf;
  974.     int buflen;
  975. {
  976.     register char *cp;
  977.     register int i;
  978.  
  979.     cp = buf;
  980.     while (np != NULL) {
  981.         if ((i = strlen(np->n_dname))+1 >= buflen) {
  982.             *cp = '\0';
  983.             syslog(LOG_ERR, "domain name too long: %s...\n", buf);
  984.             strcpy(buf, "Name_Too_Long");
  985.             return;
  986.         }
  987.         if (cp != buf)
  988.             *cp++ = '.';
  989.         (void) strcpy(cp, np->n_dname);
  990.         cp += i;
  991.         buflen -= (i+1);
  992.         np = np->n_parent;
  993.     }
  994.     *cp = '\0';
  995. }
  996.  
  997. /*
  998.  * Do a zone transfer. SOA record already sent.
  999.  */
  1000. doaxfr(np, rfp, isroot, top)
  1001.     register struct namebuf *np;
  1002.     FILE *rfp;
  1003.     int isroot;
  1004.     struct namebuf *top;
  1005. {
  1006.     register struct databuf *dp;
  1007.     register int n;
  1008.     struct hashbuf *htp;
  1009.     struct databuf *gdp;    /* glue databuf */
  1010.     struct namebuf *gnp;    /* glue namebuf */
  1011.     struct namebuf *tnp;
  1012.     struct databuf *tdp;
  1013.     struct namebuf **npp, **nppend;
  1014.     char msg[PACKETSZ];
  1015.     char *cp;
  1016.     char *fname;
  1017.     char dname[MAXDNAME];
  1018.     HEADER *hp = (HEADER *) msg;
  1019.     int fndns;
  1020.  
  1021. #ifdef DEBUG
  1022.     if (debug && isroot)
  1023.         fprintf(ddt,"doaxfr()\n");
  1024. #endif
  1025.     fndns = 0;
  1026.     hp->id = 0;
  1027.     hp->opcode = QUERY;
  1028.     hp->aa = hp->tc = hp->ra = hp->pr = hp->rd = 0;
  1029.     hp->qr = 1;
  1030.     hp->rcode = NOERROR;
  1031.     hp->qdcount = 0;
  1032.     hp->ancount = htons(1);
  1033.     hp->nscount = 0;
  1034.     hp->arcount = 0;
  1035.     cp = msg + sizeof(HEADER);
  1036.     getname(np, dname, sizeof(dname));
  1037.  
  1038.     /* first do the NS records */
  1039.     for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  1040.         if (dp->d_type == T_NS) {
  1041.         fndns = 1;
  1042.         if ((n = make_rr(dname, dp, cp, sizeof(msg)-sizeof(HEADER), 0)) < 0)
  1043.             continue;
  1044.         fwritemsg(rfp, msg, n + sizeof(HEADER));
  1045.         if (!isroot) {
  1046.             /*  Glue the sub domains together by sending 
  1047.              *  the address records for the sub domain
  1048.              *  name servers along if they belong at
  1049.              *  or below the subdomain
  1050.              */
  1051.              htp = hashtab;
  1052.             cp = msg + sizeof(HEADER);
  1053.              gnp = nlookup(dp->d_data, &htp, &fname, 0);
  1054.              if (gnp == NULL || fname != dp->d_data)
  1055.              continue;
  1056.             for (tnp = gnp; tnp != NULL; tnp = tnp->n_parent)
  1057.             if ( tnp == top )
  1058.                 break;
  1059.             if ( tnp == NULL )
  1060.             continue;  /* name server is not in a (sub)domain */
  1061.             for (tnp = gnp; tnp != top; tnp = tnp->n_parent) {
  1062.             for (tdp = tnp->n_data; tdp != NULL; tdp = tdp->d_next)
  1063.                 if (tdp->d_type == T_NS)
  1064.                 break;
  1065.             if (tdp != NULL)
  1066.                 break;
  1067.             }
  1068.             if (tnp == top)
  1069.             continue;  /* name server is not in a subdomain */
  1070.              for(gdp=gnp->n_data; gdp != NULL; gdp=gdp->d_next) {
  1071.              if (gdp->d_type != T_A || stale(gdp))
  1072.                  continue;
  1073.              if ((n = make_rr(fname, gdp, cp,
  1074.                      sizeof(msg)-sizeof(HEADER), 0)) < 0)
  1075.                  continue;
  1076.              fwritemsg(rfp, msg, n + sizeof(HEADER));
  1077.              }
  1078.         }
  1079.         }
  1080.     }
  1081.     /* no need to send anything else because of delegation */
  1082.     if (!isroot && fndns)
  1083.         return;
  1084.  
  1085.     /* do the rest of the data records */
  1086.     for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  1087.         /*
  1088.          * Skip the root SOA record (marks end of data);
  1089.          * don't send SOA for subdomains, as we're not sending them.
  1090.          * Skip the NS record because we did it first
  1091.          */
  1092.         if (dp->d_type == T_SOA || dp->d_type == T_NS)
  1093.             continue;
  1094.         if (dp->d_zone == 0 || stale(dp))
  1095.             continue;
  1096.         if ((n = make_rr(dname, dp, cp, sizeof(msg)-sizeof(HEADER), 0)) < 0)
  1097.             continue;
  1098.         fwritemsg(rfp, msg, n + sizeof(HEADER));
  1099.     }
  1100.  
  1101.     /* finally do subdomains */
  1102.     if (np->n_hash == NULL)
  1103.         return;
  1104.     npp = np->n_hash->h_tab;
  1105.     nppend = npp + np->n_hash->h_size;
  1106.     while (npp < nppend) {
  1107.         for (np = *npp++; np != NULL; np = np->n_next) {
  1108.             doaxfr(np, rfp, 0, top);
  1109.         }
  1110.     }
  1111. #ifdef DEBUG
  1112.     if (debug && isroot)
  1113.         fprintf(ddt,"exit doaxfr()\n");
  1114. #endif
  1115. }
  1116.  
  1117. #ifdef ALLOW_UPDATES
  1118. /*
  1119.  * Called by UPDATE{A,D,DA,M,MA} to initiate a dynamic update.  If this is the
  1120.  * primary server for the zone being updated, we update the zone's serial
  1121.  * number and then call doupdate directly. If this is a secondary, we just
  1122.  * forward the update; this way, if the primary update fails (e.g., if the
  1123.  * primary is unavailable), we don't update the secondary; if the primary
  1124.  * update suceeds, ns_resp will get called with the response (when it comes
  1125.  * in), and then update the secondary's copy.
  1126.  */
  1127. InitDynUpdate(hp, nsp, msg, msglen, startcp, from, qsp, dfd)
  1128.     register HEADER *hp;
  1129.     struct databuf *nsp[];
  1130.     char *msg;
  1131.     int msglen;
  1132.     u_char *startcp;
  1133.     struct sockaddr_in *from;
  1134.     struct qstream *qsp;
  1135.     int dfd;
  1136. {
  1137.     struct zoneinfo *zp;
  1138.     char dnbuf[MAXDNAME];
  1139.     struct hashbuf *htp = hashtab;    /* lookup relative to root */
  1140.     struct namebuf *np;
  1141.     struct databuf *olddp, *newdp, *dp;
  1142.     struct databuf **nspp;
  1143.     char *fname;
  1144.     register u_char *cp = startcp;
  1145.     short class, type;
  1146.     int n, size, zonenum;
  1147.     char ZoneName[MAXDNAME], *znp;
  1148.  
  1149.     if ((n = dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) {
  1150. #ifdef DEBUG
  1151.         if (debug)
  1152.             fprintf(ddt,"FORMERR InitDynUpdate expand name failed\n");
  1153. #endif
  1154.         hp->rcode = FORMERR;
  1155.         return(FORMERR);
  1156.     }
  1157.     cp += n;
  1158.     GETSHORT(type, cp);
  1159.     if (type == T_SOA) {    /* T_SOA updates not allowed */
  1160.         hp->rcode = REFUSED;
  1161. #ifdef DEBUG
  1162.         if (debug)
  1163.             fprintf(ddt, "InitDynUpdate: REFUSED - SOA update\n");
  1164. #endif
  1165.         return(REFUSED);
  1166.     }
  1167.     GETSHORT(class, cp);
  1168.     cp += sizeof(u_long);
  1169.     GETSHORT(size, cp);
  1170. /****XXX - need bounds checking here ****/
  1171.     cp += size;
  1172.  
  1173.     if ((zonenum = findzone(dnbuf, class)) == 0) {  /* zone not found */
  1174.         hp->rcode = NXDOMAIN;
  1175.         return(NXDOMAIN);
  1176.     }
  1177.     zp = &zones[zonenum];
  1178.  
  1179.     /* Disallow updates for which we aren't authoratative.  Note: the
  1180.        following test doesn't work right:  If it's for a non-local zone,
  1181.        we will think it's a primary but be unable to lookup the namebuf,
  1182.        thus returning 'NXDOMAIN' */
  1183.     if (zp->z_type != Z_PRIMARY && zp->z_type != Z_SECONDARY) {
  1184.         hp->rcode = REFUSED;
  1185. #ifdef DEBUG
  1186.         if (debug)
  1187.             fprintf(ddt, "InitDynUpdate: REFUSED - non-primary, non-sedondary update\n");
  1188. #endif
  1189.         return(REFUSED);
  1190.     }
  1191.     if (!(zp->z_state & Z_DYNAMIC)) {
  1192.         hp->rcode = REFUSED;
  1193. #ifdef DEBUG
  1194.         if (debug)
  1195.             fprintf(ddt, "InitDynUpdate: REFUSED - dynamic flag not set for zone\n");
  1196. #endif
  1197.         return(REFUSED);
  1198.     }
  1199.  
  1200.     /*
  1201.      * Lookup the zone namebuf.  Lookup "xyz" not "xyz.", since
  1202.      * otherwise the lookup fails, because '.' may have a nil n_hash
  1203.      * associated with it.
  1204.      */
  1205.     strcpy(ZoneName, zp->z_origin);
  1206.     znp = &ZoneName[strlen(ZoneName) - 1];
  1207.     if (*znp == '.')
  1208.         *znp = NULL;
  1209.     np = nlookup(ZoneName, &htp, &fname, 0);
  1210.     if ((np == NULL) || (fname != ZoneName)) {
  1211. #ifdef DEBUG
  1212.         if (debug)
  1213.             fprintf(ddt, "InitDynUpdate: lookup failed on zone (%s)\n",
  1214.                 ZoneName);
  1215. #endif DEBUG
  1216.             syslog(LOG_ERR, "InitDynUpdate: lookup failed on zone (%s)\n",
  1217.                ZoneName);
  1218.         hp->rcode = NXDOMAIN;
  1219.         return(NXDOMAIN);
  1220.     }
  1221.  
  1222.     /*
  1223.      * If this is the primary copy increment the serial number.  Don't
  1224.      * increment the serial number if this is a secondary; this way, if 2
  1225.      * different secondaries both update the primary, they will both have
  1226.      * lower serial numbers than the primary has, and hence eventually
  1227.      * refresh and get all updates and become consistent.
  1228.      *
  1229.      * Note that the serial number must be incremented in both the zone
  1230.      * data structure and the zone's namebuf.
  1231.      */
  1232.     switch (zp->z_type) {
  1233.     case Z_SECONDARY:        /* forward update to primary */
  1234.         nspp = nsp;
  1235.         dp = np->n_data;
  1236.         while (dp != NULL) {
  1237.             if (match(dp, class, T_NS)) {
  1238.                 if (nspp < &nsp[NSMAX-1])
  1239.                     *nspp++ = dp;
  1240.                 else
  1241.                     break;
  1242.             }
  1243.             dp = dp->d_next;
  1244.         }
  1245.         *nspp = NULL; /* Delimiter */
  1246. #ifdef LAME_DELEGATION
  1247.         if (ns_forw(nsp, msg, msglen, from, qsp, dfd, NULL, np) < 0) {
  1248. #else /* LAME DELEGATION */
  1249.         if (ns_forw(nsp, msg, msglen, from, qsp, dfd, NULL) < 0) {
  1250. #endif /* LAME DELEGATION */
  1251.             hp->rcode = SERVFAIL;
  1252.             return(SERVFAIL);
  1253.         }
  1254.         return(FORWARDED);
  1255.  
  1256.     case Z_PRIMARY:
  1257.         zp->z_serial++;
  1258.         olddp = np->n_data; /* old databuf */
  1259.         /* Find the SOA record */
  1260.         for (olddp = np->n_data; olddp != NULL; olddp = olddp->d_next)
  1261.             if (match(olddp, class, T_SOA))
  1262.                 break;
  1263.         if (olddp == NULL) {
  1264. #ifdef DEBUG
  1265.             if (debug)
  1266.                 fprintf(ddt,"InitDynUpdate: Couldn't find SOA record for '%s'\n",
  1267.                         ZoneName);
  1268. #endif DEBUG
  1269.             syslog(LOG_ERR,
  1270.                "InitDynUpdate: Couldn't find SOA record for '%s'\n"
  1271. ,
  1272.                ZoneName);
  1273.             hp->rcode = NXDOMAIN;
  1274.             return(NXDOMAIN);
  1275.         }
  1276.         newdp = savedata(olddp->d_class, olddp->d_type, olddp->d_ttl,
  1277.                  olddp->d_data, olddp->d_size);
  1278.         newdp->d_zone = olddp->d_zone;
  1279.         cp = (u_char *)newdp->d_data;
  1280.         cp += strlen(cp) + 1; /* skip origin string */
  1281.         cp += strlen(cp) + 1; /* skip in-charge string */
  1282.         putlong((u_long)(zp->z_serial), cp);
  1283. #ifdef DEBUG
  1284.         if (debug >= 4) {
  1285.             fprintf(ddt, "after stuffing data into newdp:\n");
  1286.             printSOAdata(newdp);
  1287.         }
  1288. #endif DEBUG
  1289.  
  1290.         if ((n = db_update(ZoneName, olddp, newdp, DB_DELETE,
  1291.                    hashtab)) != NOERROR) {
  1292. #ifdef DEBUG
  1293.             if (debug)
  1294.                 fprintf(ddt,"InitDynUpdate: SOA update failed\n");
  1295. #endif DEBUG
  1296.             hp->rcode = NOCHANGE;
  1297.             return(NOCHANGE);
  1298.         }
  1299.  
  1300.         /* Now update the RR itself */
  1301.         if (doupdate(msg, msglen, msg + sizeof(HEADER),
  1302.                  zonenum, (struct databuf *)0, DB_NODATA) < 0) {
  1303. #ifdef DEBUG
  1304.             if (debug)
  1305.                 fprintf(ddt,"InitDynUpdate: doupdate failed\n");
  1306. #endif DEBUG
  1307.             /* doupdate fills in rcode */
  1308.             return(hp->rcode);
  1309.         }
  1310.         zp->hasChanged++;
  1311.         return(NOERROR);
  1312.     }
  1313. }
  1314.  
  1315. #ifdef DEBUG
  1316. /*
  1317.  * Print the contents of the data in databuf pointed to by dp for an SOA record
  1318.  */
  1319. printSOAdata(dp)
  1320.     struct databuf *dp;
  1321. {
  1322.     register u_char *cp;
  1323.  
  1324.     if (!debug)
  1325.         return;  /* Otherwise fprintf to ddt will bomb */
  1326.     cp = (u_char *)dp->d_data;
  1327.     fprintf(ddt, "printSOAdata(%x): origin(%x)='%s'\n", dp, cp, cp);
  1328.     cp += strlen(cp) + 1; /* skip origin string */
  1329.     fprintf(ddt, "printSOAdata: in-charge(%x)='%s'\n", cp, cp);
  1330.     cp += strlen(cp) + 1; /* skip in-charge string */
  1331.     fprintf(ddt, "printSOAdata: serial(%x)=%d\n", cp, _getlong(cp));
  1332. }
  1333. #endif DEBUG
  1334. #endif ALLOW_UPDATES
  1335.  
  1336. struct databuf *
  1337. rm_datum(dp, np, pdp)
  1338. register struct databuf *pdp, *dp;
  1339. register struct namebuf *np;
  1340. {
  1341.     register struct databuf *ndp = dp->d_next;
  1342.  
  1343. #ifdef DEBUG
  1344.     if (debug > 2)
  1345.         fprintf(ddt, "rm_datum(%x, %x, %x) -> %x\n",
  1346.             dp, np->n_data, pdp, ndp);
  1347. #endif DEBUG
  1348.     if (pdp == NULL)
  1349.         np->n_data = ndp;
  1350.     else
  1351.         pdp->d_next = ndp;
  1352.     rminv(dp);
  1353.     (void) free((char *)dp);
  1354.     return(ndp);
  1355. }
  1356.  
  1357. startxfr(qsp, np, msg, msglen)
  1358.     struct qstream *qsp;
  1359.     struct namebuf *np;
  1360.     char    *msg;
  1361.     int    msglen;
  1362. {
  1363.     register FILE *rfp;
  1364.     int fdstat;
  1365.  
  1366. #ifdef DEBUG
  1367.     if (debug >= 5)
  1368.         fprintf(ddt,"startxfr()\n");
  1369. #endif
  1370.     /*
  1371.      * child does the work while
  1372.      * the parent continues
  1373.      */
  1374.     if (fork() == 0) {
  1375. #ifdef DEBUG
  1376.         if (debug >= 5)
  1377.             fprintf(ddt,"startxfr: child pid %d\n", getpid());
  1378. #endif
  1379.         rfp = fdopen(qsp->s_rfd, "w");
  1380.         setproctitle("zone XFR to", qsp->s_rfd);
  1381.         fdstat = fcntl(qsp->s_rfd, F_GETFL, 0);
  1382.         if (fdstat != -1)
  1383.             (void) fcntl(qsp->s_rfd, F_SETFL, fdstat & ~FNDELAY);
  1384.         fwritemsg(rfp, msg, msglen);
  1385.         doaxfr(np, rfp, 1, np);
  1386.         fwritemsg(rfp, msg, msglen);
  1387.         (void) fflush(rfp);
  1388.         exit(0);
  1389.     }
  1390.     sqrm(qsp);
  1391. }
  1392.